/*
    libhdvbd - Library for building sophisticated DVB applications
    Copyright (C) 2012 Tony Houghton <h@realh.co.uk>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <glib.h>

#include <string.h>

#include "codes.h"
#include "i18n.h"
#include "streaminfo.h"

dmx_pes_type_t
hdvb_stream_info_get_pes_type(const HdvbPMTStreamInfo *si)
{
    GList *descriptors;
    GList *link;
    dmx_pes_type_t result = DMX_PES_OTHER;
    
    if (HDVB_STREAM_TYPE_IS_VIDEO(si->stream_type))
        return DMX_PES_VIDEO;
    if (HDVB_STREAM_TYPE_IS_AUDIO(si->stream_type))
        return DMX_PES_AUDIO;
    if (si->stream_type != HDVB_STREAM_TYPE_PRIVATE_PES)
        return DMX_PES_OTHER;
    descriptors = hdvb_section_list_pmt_stream_info_descriptors(si);
    for (link = descriptors; link; link = g_list_next(link))
    {
        const HdvbDescriptor *desc = link->data;
        
        switch (desc->h.tag)
        {
            case HDVB_DTAG_TELETEXT:
                result = DMX_PES_TELETEXT;
                break;
            case HDVB_DTAG_SUBTITLING:
                result = DMX_PES_SUBTITLE;
                break;
            case HDVB_DTAG_AC3:
            case HDVB_DTAG_ENHANCED_AC3:
            case HDVB_DTAG_DTS:
            case HDVB_DTAG_AAC:
                result = DMX_PES_AUDIO;
                break;
        }
        if (result != DMX_PES_OTHER)
            break;
    }
    g_list_free(descriptors);
    return result;
}

HdvbServicePidsInfo *
hdvb_service_pids_info_copy(const HdvbServicePidsInfo *src)
{
    HdvbServicePidsInfo *dest = g_new(HdvbServicePidsInfo, 1);
    GList *link;
    
    *dest = *src;
    dest->streams = NULL;
    for (link = src->streams; link; link = g_list_next(link))
    {
        HdvbStreamInfo *src_info = link->data;
        HdvbStreamInfo *dest_info = g_new(HdvbStreamInfo, 1);
        gsize pi_size = HDVB_SECTION_PMT_STREAM_INFO_DESCRIPTORS_LENGTH(
                src_info->pmt_info) + 5;
        
        *dest_info = *src_info;
        dest_info->pmt_info = g_malloc(pi_size);
        memcpy(dest_info->pmt_info, src_info->pmt_info, pi_size);
        dest->streams = g_list_append(dest->streams, dest_info);
    }
    return dest;
}

void
hdvb_service_pids_info_delete(HdvbServicePidsInfo *info)
{
    GList *link;
    
    for (link = info->streams; link; link = g_list_next(link))
    {
        HdvbStreamInfo *sinfo = link->data;
        
        g_free(sinfo->pmt_info);
        g_free(sinfo);
    }
    g_list_free(info->streams);
    g_free(info);
}

static void
hdvb_service_pids_info_request_pid_filter(HdvbReceiver *rcv, int pid,
        dmx_pes_type_t pes_type, int stype, int *err)
{
    g_debug("Requesting pid %d\t(%02x)", pid, stype);
    int result = hdvb_receiver_request_ts_filter(rcv, pid, pes_type);
    
    if (result)
    {
        g_warning(_("Error requsting pid %d filter from receiver %d:%d: %s"),
                pid, rcv->adapter, rcv->frontend, strerror(result));
        if (!*err)
            *err = result;
    }
}

int
hdvb_service_pids_info_request_filters(const HdvbServicePidsInfo *info,
        HdvbReceiver *rcv)
{
    int err = 0;
    GList *link;
    
    hdvb_service_pids_info_request_pid_filter(rcv, HDVB_PID_PAT,
            DMX_PES_OTHER, 0, &err);
    hdvb_service_pids_info_request_pid_filter(rcv, info->pmt_pid,
            DMX_PES_OTHER, 0, &err);
    hdvb_service_pids_info_request_pid_filter(rcv, info->pcr_pid,
            DMX_PES_PCR, 0, &err);
    for (link = info->streams; link; link = g_list_next(link))
    
    {
        HdvbStreamInfo *strm = link->data;
        
        /* Any stream in here with OTHER type is useless to us ATM */
        if (strm->pes_type != DMX_PES_OTHER)
        {
            hdvb_service_pids_info_request_pid_filter(rcv, strm->pid,
                    strm->pes_type, strm->stream_type, &err);
        }
    }
    return err;
}
